"""A simple interface to libmtp. To use, create an instance of the MTP class. THIS MODULE IS NOT THREAD SAFE! You can call code from any thread but if you call something from one thread while another thread is doing something with this module bad things will happen."""
ctypedef unsigned char uint8_t
ctypedef unsigned short int uint16_t
ctypedef unsigned int uint32_t
ctypedef unsigned long long int uint64_t

cdef extern from "string.h":
	char*strdup(char*)
	void free(void*)

#extern structs/functions from libmtp:
cdef extern from "libmtp.h":
	void LIBMTP_Init()

	struct LIBMTP_mtpdevice_struct:
		pass
	ctypedef LIBMTP_mtpdevice_struct LIBMTP_mtpdevice_t

	ctypedef enum LIBMTP_filetype_t:
		LIBMTP_FILETYPE_WAV=0
		LIBMTP_FILETYPE_MP3
		LIBMTP_FILETYPE_WMA
		LIBMTP_FILETYPE_OGG
		LIBMTP_FILETYPE_AUDIBLE
		LIBMTP_FILETYPE_MP4
		LIBMTP_FILETYPE_UNDEF_AUDIO
		LIBMTP_FILETYPE_WMV
		LIBMTP_FILETYPE_AVI
		LIBMTP_FILETYPE_MPEG
		LIBMTP_FILETYPE_ASF
		LIBMTP_FILETYPE_QT
		LIBMTP_FILETYPE_UNDEF_VIDEO
		LIBMTP_FILETYPE_JPEG
		LIBMTP_FILETYPE_JFIF
		LIBMTP_FILETYPE_TIFF
		LIBMTP_FILETYPE_BMP
		LIBMTP_FILETYPE_GIF
		LIBMTP_FILETYPE_PICT
		LIBMTP_FILETYPE_PNG
		LIBMTP_FILETYPE_VCALENDAR1
		LIBMTP_FILETYPE_VCALENDAR2
		LIBMTP_FILETYPE_VCARD2
		LIBMTP_FILETYPE_VCARD3
		LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT
		LIBMTP_FILETYPE_WINEXEC
		LIBMTP_FILETYPE_TEXT
		LIBMTP_FILETYPE_HTML
		LIBMTP_FILETYPE_FIRMWARE
		LIBMTP_FILETYPE_AAC
		LIBMTP_FILETYPE_MEDIACARD
		LIBMTP_FILETYPE_FLAC
		LIBMTP_FILETYPE_MP2
		LIBMTP_FILETYPE_M4A
		LIBMTP_FILETYPE_DOC
		LIBMTP_FILETYPE_XML
		LIBMTP_FILETYPE_XLS
		LIBMTP_FILETYPE_PPT
		LIBMTP_FILETYPE_MHT
		LIBMTP_FILETYPE_JP2
		LIBMTP_FILETYPE_JPX
		LIBMTP_FILETYPE_UNKNOWN

	struct LIBMTP_track_struct
	ctypedef LIBMTP_track_struct LIBMTP_track_t
	struct LIBMTP_track_struct:
		uint32_t item_id
		uint32_t parent_id
		uint32_t storage_id
		char *title
		char *artist
		char *composer
		char *genre
		char *album
		char *date
		char *filename
		uint16_t tracknumber
		uint32_t duration
		uint32_t samplerate
		uint16_t nochannels
		uint32_t wavecodec
		uint32_t bitrate
		uint16_t bitratetype
		uint16_t rating
		uint32_t usecount
		uint64_t filesize
		LIBMTP_filetype_t filetype
		LIBMTP_track_t *next

	LIBMTP_track_t*LIBMTP_new_track_t()
	void LIBMTP_destroy_track_t(LIBMTP_track_t*)
	
	struct LIBMTP_file_struct
	ctypedef LIBMTP_file_struct LIBMTP_file_t
	struct LIBMTP_file_struct:
		uint32_t item_id
		uint32_t parent_id
		uint32_t storage_id
		char *filename
		uint64_t filesize
		LIBMTP_filetype_t filetype
		LIBMTP_file_t *next
		
	LIBMTP_file_t*LIBMTP_new_file_t()
	void LIBMTP_destroy_file_t(LIBMTP_file_t*)

	LIBMTP_mtpdevice_t* LIBMTP_Get_First_Device() nogil
	void 	LIBMTP_Release_Device(LIBMTP_mtpdevice_t*) nogil

	void LIBMTP_Dump_Errorstack(LIBMTP_mtpdevice_t*)
	void LIBMTP_Clear_Errorstack(LIBMTP_mtpdevice_t*)

	ctypedef int (* LIBMTP_progressfunc_t) (uint64_t, uint64_t,void*)

	char*	LIBMTP_Get_Manufacturername(LIBMTP_mtpdevice_t*)
	char*	LIBMTP_Get_Modelname(LIBMTP_mtpdevice_t*)
	char*	LIBMTP_Get_Serialnumber(LIBMTP_mtpdevice_t*)
	char*	LIBMTP_Get_Deviceversion(LIBMTP_mtpdevice_t*)
	char*	LIBMTP_Get_Friendlyname(LIBMTP_mtpdevice_t*)
	int		LIBMTP_Set_Friendlyname(LIBMTP_mtpdevice_t*, char*)
	int		LIBMTP_Get_Batterylevel(LIBMTP_mtpdevice_t *,uint8_t *,uint8_t *)
	LIBMTP_file_t *LIBMTP_Get_Filelisting_With_Callback(LIBMTP_mtpdevice_t *, LIBMTP_progressfunc_t ,void *) nogil
	char* LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t)
	LIBMTP_file_t *LIBMTP_Get_Filemetadata(LIBMTP_mtpdevice_t *, uint32_t)
	LIBMTP_track_t *LIBMTP_Get_Tracklisting_With_Callback(LIBMTP_mtpdevice_t *, LIBMTP_progressfunc_t ,void *) nogil
	LIBMTP_track_t *LIBMTP_Get_Trackmetadata(LIBMTP_mtpdevice_t *, uint32_t)
	int LIBMTP_Get_File_To_File(LIBMTP_mtpdevice_t*, uint32_t, char * , LIBMTP_progressfunc_t ,void *) nogil
	int LIBMTP_Get_Track_To_File(LIBMTP_mtpdevice_t*, uint32_t, char * , LIBMTP_progressfunc_t ,void *) nogil
	int	LIBMTP_Send_Track_From_File(LIBMTP_mtpdevice_t *, char *, LIBMTP_track_t *, LIBMTP_progressfunc_t ,void *) nogil
	int	LIBMTP_Send_File_From_File(LIBMTP_mtpdevice_t *, char *, LIBMTP_file_t *,  LIBMTP_progressfunc_t ,void *) nogil

#define some errors (taken from pymtp)
class NoDeviceConnected(Exception): 
	"""Raised when there isn't a device connected to the USB bus"""
	pass
class AlreadyConnected(Exception):
	"""Raised when we're already connected to a device and there is an attempt to connect"""
	pass
class UnsupportedCommand(Exception): 
	"""Raised when the connected device does not support the command issued"""
	pass
class CommandFailed(Exception): 
	"""Raised when the connected device returned an error when tryingto execute a command"""
	pass
class NotConnected(Exception): 
	"""Raised when a command is called and the device is not connected"""
	pass
class ObjectNotFound(Exception):
	"""Raised when a command tries to get an object that doesn't exist"""
	pass

#convenience functions for managing dup'ed strings in Tracks, Files, etc
cdef void replace_string_dup(char**val,char *newval):
	if val[0]!=NULL:
		free(val[0])
	val[0]=NULL
	if newval:
		if newval[0]:
			val[0]=strdup(newval)
cdef object safe_to_string(char*val):
	if val == NULL:
		return ""
	else:
		return val

cdef class LIBMTP_File:
	"""Representation of a track for transfer to of from a device. It may be changed when passed to other functions"""
	cdef LIBMTP_file_t*file

	def __cinit__(self):
		self.file=LIBMTP_new_file_t()
		if(self.file==NULL):
			raise MemoryError
	def __dealloc__(self):
		LIBMTP_destroy_file_t(self.file)
	def __repr__(self):
		return "%s (%s)" % (self.filename, self.file.item_id)
	def __init__(self,**kwds):
		for k,v in kwds.iteritems():
			self.__setattr__(k,v)

	property item_id    :
		def __get__(self):return self.file.item_id    
		def __set__(self,val):self.file.item_id   =val
	property parent_id  :
		def __get__(self):return self.file.parent_id  
		def __set__(self,val):self.file.parent_id =val
	property storage_id :
		def __get__(self):return self.file.storage_id 
		def __set__(self,val):self.file.storage_id=val
	property filename :
		def __get__(self):return safe_to_string(self.file.filename )
		def __set__(self,val):replace_string_dup(&self.file.filename ,val)
	property filesize   :
		def __get__(self):return self.file.filesize   
		def __set__(self,val):self.file.filesize  =val
	property filetype   :
		def __get__(self):return self.file.filetype   
		def __set__(self,val):self.file.filetype  =val

cdef object file_copy_internal(LIBMTP_File obj,LIBMTP_file_t*copy_data):
	cdef LIBMTP_file_t*new_data=LIBMTP_new_file_t()
	if new_data==NULL:
		raise MemoryError
	LIBMTP_destroy_file_t(obj.file)
	obj.file=new_data
	obj.file[0]=copy_data[0]
	obj.file.next=NULL

cdef class LIBMTP_Track:
	"""Representation of a track for transfer to of from a device. It may be changed when passed to other functions"""
	cdef LIBMTP_track_t*track

	def __cinit__(self):
		self.track=LIBMTP_new_track_t()
		if(self.track==NULL):
			raise MemoryError
	def __dealloc__(self):
		if(self.track):
			LIBMTP_destroy_track_t(self.track)
	def __repr__(self):
		return "%s - %s (%s)" % (self.artist, self.title, self.item_id)
	def __init__(self,**kwds):
		for k,v in kwds.iteritems():
			self.__setattr__(k,v)

	#properties for setting/getting. string ones call safetyp functions to help
	property item_id    :
		def __get__(self):return self.track.item_id    
		def __set__(self,val):self.track.item_id    =val
	property parent_id  :
		def __get__(self):return self.track.parent_id  
		def __set__(self,val):self.track.parent_id  =val
	property storage_id :
		def __get__(self):return self.track.storage_id 
		def __set__(self,val):self.track.storage_id =val
	property title    :
		def __get__(self):return safe_to_string(self.track.title    )
		def __set__(self,val):replace_string_dup(&self.track.title    ,val)
	property artist   :
		def __get__(self):return safe_to_string(self.track.artist   )
		def __set__(self,val):replace_string_dup(&self.track.artist   ,val)
	property composer :
		def __get__(self):return safe_to_string(self.track.composer )
		def __set__(self,val):replace_string_dup(&self.track.composer ,val)
	property genre    :
		def __get__(self):return safe_to_string(self.track.genre    )
		def __set__(self,val):replace_string_dup(&self.track.genre    ,val)
	property album    :
		def __get__(self):return safe_to_string(self.track.album    )
		def __set__(self,val):replace_string_dup(&self.track.album    ,val)
	property date     :
		def __get__(self):return safe_to_string(self.track.date     )
		def __set__(self,val):replace_string_dup(&self.track.date     ,val)
	property filename :
		def __get__(self):return safe_to_string(self.track.filename )
		def __set__(self,val):replace_string_dup(&self.track.filename ,val)
	property tracknumber :
		def __get__(self):return self.track.tracknumber 
		def __set__(self,val):self.track.tracknumber=val
	property duration    :
		def __get__(self):return self.track.duration    
		def __set__(self,val):self.track.duration   =val
	property samplerate  :
		def __get__(self):return self.track.samplerate  
		def __set__(self,val):self.track.samplerate =val
	property nochannels  :
		def __get__(self):return self.track.nochannels  
		def __set__(self,val):self.track.nochannels =val
	property wavecodec   :
		def __get__(self):return self.track.wavecodec   
		def __set__(self,val):self.track.wavecodec  =val
	property bitrate     :
		def __get__(self):return self.track.bitrate     
		def __set__(self,val):self.track.bitrate    =val
	property bitratetype :
		def __get__(self):return self.track.bitratetype 
		def __set__(self,val):self.track.bitratetype=val
	property rating      :
		def __get__(self):return self.track.rating      
		def __set__(self,val):self.track.rating     =val
	property usecount    :
		def __get__(self):return self.track.usecount    
		def __set__(self,val):self.track.usecount   =val
	property filesize    :
		def __get__(self):return self.track.filesize    
		def __set__(self,val):self.track.filesize   =val
	property filetype   :
		def __get__(self):return self.track.filetype   
		def __set__(self,val):self.track.filetype  =val

cdef object track_copy_internal(LIBMTP_Track obj,LIBMTP_track_t*copy_data):
	cdef LIBMTP_track_t*new_data=LIBMTP_new_track_t()
	if new_data==NULL:
		raise MemoryError
	LIBMTP_destroy_track_t(obj.track)
	obj.track=new_data
	obj.track[0]=copy_data[0]
	obj.track.next=NULL

#generic callback function
cdef int MTP_Callback (uint64_t sent, uint64_t total,void* data) with gil:
	#bodge to work around libmtp data being const:
	tuple=<object>data
	callback=tuple[0]
	user_data=tuple[1]
	result=None
	try:
		if callback is not None:
			if user_data is not None:
				result=callback(total,sent,user_data)
			else:
				result=callback(total,sent)
	except:
		traceback.print_exc()
	if result is None:
		return 0
	else:
		return 1


cdef class MTP:
	"""The MTP object. This is the main wrapper around libmtp"""

	cdef LIBMTP_mtpdevice_t*device

	cdef object check_connected(self):
		if (self.device==NULL):
			raise NotConnected

	cdef object debug_stack(self):
		self.check_connected()
		LIBMTP_Dump_Errorstack(self.device)
		LIBMTP_Clear_Errorstack(self.device)
		raise CommandFailed

	def __cinit__(self):
		self.device=NULL;
	def __dealloc__(self):
		if(self.device):
			LIBMTP_Release_Device(self.device)

	def connect(self):
		"""Initializes the MTP connection to the device"""
		if (self.device!=NULL):
			raise AlreadyConnected
		with nogil:
			self.device=LIBMTP_Get_First_Device()
		if (self.device==NULL):
			raise NoDeviceConnected

	def disconnect(self):
		"""Disconnects the MTP device"""
		self.check_connected()
		with nogil:
			LIBMTP_Release_Device(self.device)
		self.device=NULL
	
	def get_devicename(self):
		"""Returns the connected device's `friendly name' (also known as the owner name)"""
		self.check_connected()
		return LIBMTP_Get_Friendlyname(self.device)

	def set_devicename(self, name):
		"""Changes the connected device's 'friendly name'"""
		self.check_connected()
		if LIBMTP_Set_Friendlyname(self.device,name) !=0:
			self.debug_stack()

	def get_serialnumber(self):
		"""Returns the connected device's serial number as a string"""
		self.check_connected()
		return LIBMTP_Get_Serialnumber(self.device)

	def get_manufacturer(self):
		"""Return the connected device's manufacturer"""
		self.check_connected()
		return LIBMTP_Get_Manufacturername(self.device)

	def get_batterylevel(self):
		""" Returns the connected device's maximum and current battery levels"""
		self.check_connected()
		cdef uint8_t maximum_level,current_level
		if LIBMTP_Get_Batterylevel(self.device,&maximum_level,&current_level)!=0:
			self.debug_stack()
		return (maximum_level, current_level)

	def get_modelname(self):
		"""Return the connected device's model name (such as "Zen V Plus")"""
		self.check_connected()
		return LIBMTP_Get_Modelname(self.device)

	def get_deviceversion(self):
		"""Returns the connected device's version (such as firmware/hardware version)"""
		self.check_connected()
		return LIBMTP_Get_Deviceversion(self.device)

	def get_filelisting(self, callback=None,user_data=None):
		self.check_connected()
		cdef LIBMTP_file_t *data
		ret=[]
		cbud=(callback,user_data)
		with nogil:
			data=LIBMTP_Get_Filelisting_With_Callback(self.device,MTP_Callback,<void*>cbud)
		if data==NULL:
			self.debug_stack()
		cdef LIBMTP_file_t *iter
		try:
			iter=data
			while iter!=NULL:
				obj=LIBMTP_File()
				file_copy_internal(obj,iter)
				iter=iter.next
				ret.append(obj)
		finally:
			iter=data
			while iter!=NULL:
				free(iter)#only need to free, as we have copied string pointers!
				iter=iter.next
		return ret

	def get_filetype_description(self, filetype):
		self.check_connected()
		return LIBMTP_Get_Filetype_Description(filetype)

	def get_file_metadata(self, file_id):
		self.check_connected()
		file=LIBMTP_File()
		cdef LIBMTP_file_t*data
		data=LIBMTP_Get_Filemetadata(self.device, file_id)
		if data == NULL:
			raise ObjectNotFound
		try:
			file_copy_internal(file,data)
		finally:
			free(data)
		return file

	def get_tracklisting(self, callback=None,user_data=None):
		self.check_connected()
		cdef LIBMTP_track_t *data
		ret=[]
		cbud=(callback,user_data)
		with nogil:
			data=LIBMTP_Get_Tracklisting_With_Callback(self.device,MTP_Callback,<void*>cbud)
		if data==NULL:
			self.debug_stack()
		cdef LIBMTP_track_t *iter
		try:
			iter=data
			while iter!=NULL:
				obj=LIBMTP_Track()
				track_copy_internal(obj,iter)
				iter=iter.next
				ret.append(obj)
		finally:
			iter=data
			while iter!=NULL:
				free(iter)#only need to free, as we have copied string pointers!
				iter=iter.next
		return ret

	def get_track_metadata(self, file_id):
		self.check_connected()
		track=LIBMTP_Track()
		cdef LIBMTP_track_t*data
		data=LIBMTP_Get_Trackmetadata(self.device, file_id)
		if data == NULL:
			raise ObjectNotFound
		try:
			track_copy_internal(track,data)
		finally:
			free(data)
		return file

	def get_file_to_file(self, file_id, target,callback=None,user_data=None):
		self.check_connected()
		cdef int ret
		cdef char* target_c=target
		cdef int file_id_c=file_id
		cbud=(callback,user_data)
		with nogil:
			ret = LIBMTP_Get_File_To_File(self.device, file_id_c, target_c,MTP_Callback,<void*>cbud)
		if (ret != 0):
			self.debug_stack()

	def get_track_to_file(self, file_id, target,callback=None,user_data=None):
		self.check_connected()
		cdef int ret
		cdef char* target_c=target
		cdef int file_id_c=file_id
		cbud=(callback,user_data)
		with nogil:
			ret = LIBMTP_Get_Track_To_File(self.device, file_id_c, target_c,MTP_Callback,<void*>cbud)
		if (ret != 0):
			self.debug_stack()

	def find_filetype(self, filename):
		fileext = filename.lower().split(".")[-1]
		if (fileext == "wav" or fileext == "wave"):
			return LIBMTP_Filetype["WAV"]
		elif (fileext == "mp3"):
			return LIBMTP_Filetype["MP3"]
		elif (fileext == "wma"):
			return LIBMTP_Filetype["WMA"]
		elif (fileext == "ogg"):
			return LIBMTP_Filetype["OGG"]
		elif (fileext == "mp4"):
			return LIBMTP_Filetype["MP4"]
		elif (fileext == "wmv"):
			return LIBMTP_Filetype["WMV"]
		elif (fileext == "avi"):
			return LIBMTP_Filetype["AVI"]
		elif (fileext == "mpeg" or fileext == "mpg"):
			return LIBMTP_Filetype["MPEG"]
		elif (fileext == "asf"):
			return LIBMTP_Filetype["ASF"]
		elif (fileext == "qt" or fileext == "mov"):
			return LIBMTP_Filetype["QT"]
		elif (fileext == "jpeg" or fileext == "jpg"):
			return LIBMTP_Filetype["JPEG"]
		elif (fileext == "jfif"):
			return LIBMTP_Filetype["JFIF"]
		elif (fileext == "tif" or fileext == "tiff"):
			return LIBMTP_Filetype["TIFF"]
		elif (fileext == "bmp"):
			return LIBMTP_Filetype["BMP"]
		elif (fileext == "gif"):
			return LIBMTP_Filetype["GIF"]
		elif (fileext == "pic" or fileext == "pict"):
			return LIBMTP_Filetype["PICT"]
		elif (fileext == "png"):
			return LIBMTP_Filetype["PNG"]
		elif (fileext == "wmf"):
			return LIBMTP_Filetype["WINDOWSIMAGEFORMAT"]
		elif (fileext == "ics"):
			return LIBMTP_Filetype["VCALENDAR2"]
		elif (fileext == "exe" or fileext == "com" or fileext == "bat"\
		      or fileext == "dll" or fileext == "sys"):
			return LIBMTP_Filetype["WINEXEC"]
		elif (fileext == "aac"):
			return LIBMTP_Filetype["AAC"]
		elif (fileext == "mp2"):
			return LIBMTP_Filetype["MP2"]
		elif (fileext == "flac"):
			return LIBMTP_Filetype["FLAC"]
		elif (fileext == "m4a"):
			return LIBMTP_Filetype["M4A"]
		elif (fileext == "doc"):
			return LIBMTP_Filetype["DOC"]
		elif (fileext == "xml"):
			return LIBMTP_Filetype["XML"]
		elif (fileext == "xls"):
			return LIBMTP_Filetype["XLS"]
		elif (fileext == "ppt"):
			return LIBMTP_Filetype["PPT"]
		elif (fileext == "mht"):
			return LIBMTP_Filetype["MHT"]
		elif (fileext == "jp2"):
			return LIBMTP_Filetype["JP2"]
		elif (fileext == "jpx"):
			return LIBMTP_Filetype["JPX"]
		else:
			return LIBMTP_Filetype["UNKNOWN"]

	def send_file_from_file_detailed(self, source, LIBMTP_File metadata,callback=None,user_data=None):
		self.check_connected()

		if (os.path.isfile(source) == False):
			raise IOError
			
		metadata.filesize=os.stat(source).st_size

		cdef int ret
		cdef char *source_c=source
		cbud=(callback,user_data)
		with nogil:
			ret = LIBMTP_Send_File_From_File(self.device, source_c,
				metadata.file,MTP_Callback,<void*>cbud)

		if (ret != 0):
			self.debug_stack()

		return metadata.item_id

	def send_file_from_file(self, source, target,callback=None,user_data=None):
		self.check_connected()

		metadata = LIBMTP_File(filename=target,
		  filetype=self.find_filetype(source))

		return self.send_file_from_file_detailed(source,metadata,callback,user_data)

	def send_track_from_file_detailed(self, source, LIBMTP_Track metadata,callback=None,user_data=None):
		self.check_connected()

		if (os.path.exists(source) == None):
			raise IOError
		
		metadata.filesize = os.stat(source).st_size

		cdef int ret
		cdef char *source_c=source
		cbud=(callback,user_data)
		with nogil:
			ret = LIBMTP_Send_Track_From_File(self.device, source_c, metadata.track, MTP_Callback,<void*>cbud)

		if (ret != 0):
			self.debug_stack()

		return metadata.item_id

	def send_track_from_file(self, source, target, LIBMTP_Track metadata,callback=None,user_data=None):
		self.check_connected()

		metadata.filename = target
		metadata.filetype = self.find_filetype(source)

		return self.send_track_from_file_detailed(source,metadata,callback,user_data)

#built in types, formatted like in pymtp
LIBMTP_Filetype = {
	"WAV"                 :LIBMTP_FILETYPE_WAV                ,
	"MP3"                 :LIBMTP_FILETYPE_MP3                ,
	"WMA"                 :LIBMTP_FILETYPE_WMA                ,
	"OGG"                 :LIBMTP_FILETYPE_OGG                ,
	"AUDIBLE"             :LIBMTP_FILETYPE_AUDIBLE            ,
	"MP4"                 :LIBMTP_FILETYPE_MP4                ,
	"UNDEF_AUDIO"         :LIBMTP_FILETYPE_UNDEF_AUDIO        ,
	"WMV"                 :LIBMTP_FILETYPE_WMV                ,
	"AVI"                 :LIBMTP_FILETYPE_AVI                ,
	"MPEG"                :LIBMTP_FILETYPE_MPEG               ,
	"ASF"                 :LIBMTP_FILETYPE_ASF                ,
	"QT"                  :LIBMTP_FILETYPE_QT                 ,
	"UNDEF_VIDEO"         :LIBMTP_FILETYPE_UNDEF_VIDEO        ,
	"JPEG"                :LIBMTP_FILETYPE_JPEG               ,
	"JFIF"                :LIBMTP_FILETYPE_JFIF               ,
	"TIFF"                :LIBMTP_FILETYPE_TIFF               ,
	"BMP"                 :LIBMTP_FILETYPE_BMP                ,
	"GIF"                 :LIBMTP_FILETYPE_GIF                ,
	"PICT"                :LIBMTP_FILETYPE_PICT               ,
	"PNG"                 :LIBMTP_FILETYPE_PNG                ,
	"VCALENDAR1"          :LIBMTP_FILETYPE_VCALENDAR1         ,
	"VCALENDAR2"          :LIBMTP_FILETYPE_VCALENDAR2         ,
	"VCARD2"              :LIBMTP_FILETYPE_VCARD2             ,
	"VCARD3"              :LIBMTP_FILETYPE_VCARD3             ,
	"WINDOWSIMAGEFORMAT"  :LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT ,
	"WINEXEC"             :LIBMTP_FILETYPE_WINEXEC            ,
	"TEXT"                :LIBMTP_FILETYPE_TEXT               ,
	"HTML"                :LIBMTP_FILETYPE_HTML               ,
	"FIRMWARE"            :LIBMTP_FILETYPE_FIRMWARE           ,
	"AAC"                 :LIBMTP_FILETYPE_AAC                ,
	"MEDIACARD"           :LIBMTP_FILETYPE_MEDIACARD          ,
	"FLAC"                :LIBMTP_FILETYPE_FLAC               ,
	"MP2"                 :LIBMTP_FILETYPE_MP2                ,
	"M4A"                 :LIBMTP_FILETYPE_M4A                ,
	"DOC"                 :LIBMTP_FILETYPE_DOC                ,
	"XML"                 :LIBMTP_FILETYPE_XML                ,
	"XLS"                 :LIBMTP_FILETYPE_XLS                ,
	"PPT"                 :LIBMTP_FILETYPE_PPT                ,
	"MHT"                 :LIBMTP_FILETYPE_MHT                ,
	"JP2"                 :LIBMTP_FILETYPE_JP2                ,
	"JPX"                 :LIBMTP_FILETYPE_JPX                ,
	"UNKNOWN"             :LIBMTP_FILETYPE_UNKNOWN            ,
}

LIBMTP_Init()
import os
import traceback
